package cc.eddic.pratice.programmingparadigms.nginxlog.impl;

import cc.eddic.pratice.programmingparadigms.nginxlog.*;

import java.util.*;
import java.util.stream.Collectors;

public class LogReportHrjImpl implements LogReport {
    @Override
    public PageViewsAndUniqueVisitors pageViewsAndUniqueVisitors(List<NginxLogItem> items) {
        long pageViews = items.size();
        long uniqueVisitors = 0;

        Map<String, Map<String, List<NginxLogItem>>> groupByUserAgentAndIp = items.stream().collect(Collectors.groupingBy(NginxLogItem::getUserAgent, Collectors.groupingBy(NginxLogItem::getIp)));

        for (String item : groupByUserAgentAndIp.keySet()) {
            uniqueVisitors = uniqueVisitors + groupByUserAgentAndIp.get(item).keySet().size();
        }

        return new PageViewsAndUniqueVisitors(pageViews, uniqueVisitors);
    }


    @Override
    public Map<Integer, PageViewsAndUniqueVisitors> pageViewsAndUniqueVisitorsByHour(List<NginxLogItem> items) {
        Map<Integer, List<NginxLogItem>> groupByHour = new HashMap<>();
        Map<Integer, PageViewsAndUniqueVisitors> pageViewsAndUniqueVisitorsMap = new HashMap<>();

        for (NginxLogItem item : items) {

            int index = item.getTime().indexOf(":");
            String itemHour = item.getTime().substring(index + 1, index + 3);

            if (groupByHour.containsKey(Integer.valueOf(itemHour))) {
                groupByHour.get(Integer.valueOf(itemHour)).add(item);
            } else {
                List<NginxLogItem> itemList = new ArrayList<>();
                itemList.add(item);
                groupByHour.put(Integer.valueOf(itemHour), itemList);
            }
        }

        for (int hour : groupByHour.keySet()) {

            pageViewsAndUniqueVisitorsMap.put(hour, pageViewsAndUniqueVisitors(groupByHour.get(hour)));

        }

        return pageViewsAndUniqueVisitorsMap;
    }

    @Override
    public List<PathModel> pageViewsAndUniqueVisitorsByPath(List<LogItem> items) {

        PageViewsAndUniqueVisitors pvAndUv;


        Map<String, List<LogItem>> groupByPath = items.stream().collect(Collectors.groupingBy(LogItem::getPath));

        List<PathModel> pathModelList = new ArrayList<>();

        for (String path : groupByPath.keySet()) {
            pvAndUv = pageViewsAndUniqueVisitors2(groupByPath.get(path));
            pathModelList.add(new PathModel(path, pvAndUv.getPageViews(), pvAndUv.getUniqueVisitors()));
        }

        List<PathModel> a = pathModelList.stream().sorted(Comparator.comparing(PathModel::getPv).reversed()).collect(Collectors.toList());
        for(PathModel p :a){
            System.out.println(p.getPath()+"  "+p.getPv() +" "+p.getUv());
        }

        return pathModelList.stream().sorted(Comparator.comparing(PathModel::getPv).reversed()).collect(Collectors.toList());
    }

    public PageViewsAndUniqueVisitors pageViewsAndUniqueVisitors2(List<LogItem> items) {
        long pageViews = items.size();
        long uniqueVisitors = 0;

        Map<String, Map<String, List<LogItem>>> groupByUserAgentAndIp = items.stream().collect(Collectors.groupingBy(LogItem::getUserAgent, Collectors.groupingBy(LogItem::getIp)));

        for (String item : groupByUserAgentAndIp.keySet()) {
            uniqueVisitors = uniqueVisitors + groupByUserAgentAndIp.get(item).keySet().size();
        }

        return new PageViewsAndUniqueVisitors(pageViews, uniqueVisitors);
    }


}
